﻿using ComLib.ComFun;
using ComLib.ComType;
using ComUIControl;
using libcontrol;
using LogLib;
using Newtonsoft.Json;
using PipeClient;
using System;
using System.IO;
using System.IO.Ports;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace LedDemo
{
    public partial class FormLedControl : Form
    {
        /// <summary>
        /// 当一个应用程序传递数据给另一个应用程序时发送此消息
        /// </summary>
        public const int WM_COPYDATA = 0x004A;

        //MotionHandler handler = null;

        private IntPtr MonitoringWindowHandle = IntPtr.Zero;

        private const int MSG_ID = 0x1234;


        private LedControl _ledControl = null;
        public FormLedControl()
        {
            InitializeComponent();
            _ledControl = LedControl.GetInstance();
        }

        public FormLedControl(IntPtr ptr)
        {
            MonitoringWindowHandle = ptr;
            InitializeComponent();
            _ledControl = LedControl.GetInstance();
        }

        private void InitPortComBoxs()
        {
            string[] ports = SerialPort.GetPortNames();
            comboBoxComPorts.Items.Clear();
            comboBoxComPorts.Items.AddRange(ports);
            string comNo = IniFile.IniValue("Com", "Port");
            if (!string.IsNullOrEmpty(comNo))
            {
                for (int i = 0; i < comboBoxComPorts.Items.Count; i++)
                {
                    string item = comboBoxComPorts.Items[i].ToString();
                    if (item == comNo)
                    {
                        comboBoxComPorts.SelectedIndex = i;
                    }
                }
            }
        }

        private void buttonConnect_Click(object sender, EventArgs e)
        {
            OnConnected();
        }

        private bool OnConnected()
        {
            if(_ledControl.Connected)
            {
                return false;
            }
            if (comboBoxComPorts.SelectedIndex == -1)
            {
                string logInfo = "未选择有效地址: \n请选择要连接的串口号";
                Log.WriteAsync(logInfo);
                MsgBox.Show(logInfo);
                return false;
            }
            string comNo = comboBoxComPorts.SelectedItem.ToString();
            if (_ledControl.Connect(comNo))
            {
                IniFile.WriteValue("Com", "Port", comNo);
                SetButtonsEnabled(true);
                buttonConnect.Enabled = false;
                buttonDisconnect.Enabled = true;
                _ledControl.SetMsgCallBack(OnControlMsgCallback);
                labelStatus.Text = "设备已连接";
                Log.WriteAsync("设备已连接");
                if (MonitoringWindowHandle != IntPtr.Zero)
                {
                    OnAppStartupFinished();
                }
                return true;
            }
            else
            {
                labelStatus.Text = $"连接{comNo}失败, 请选择正确的串口重新连接.";
                if (MonitoringWindowHandle != IntPtr.Zero)
                {
                    OnAppStartupFinished(0, "电机控制板初始化失败!");
                }
                string logInfo = "连接{comNo}失败!\n请选择正确的串口重新连接.";
                Log.WriteAsync(logInfo);
                MsgBox.Show(logInfo);
                return false;
            }
        }

        private void SetButtonsEnabled(bool value)
        {
            radioButton1.Enabled = value;
            radioButton2.Enabled = value;
            radioButton3.Enabled = value;

            buttonLedFlash.Enabled = value;
            buttonLedOn.Enabled = value;
            buttonLedOff.Enabled = value;
        }
        private void FormLedControl_Load(object sender, EventArgs e)
        {
            InitPortComBoxs();
            if (MonitoringWindowHandle != IntPtr.Zero)
            {
                OnConnected();
                Log.WriteAsync($"灯光控制程序启动成功, 监视窗口句柄为{MonitoringWindowHandle}");
            }
        }

        private void OnControlMsgCallback(InterfaceMsg msg, string strText)
        {
            string strError = $"Name={msg.Name}, Id={msg.ID}, Msg={strText}";
            ShowInfo(strError);
        }

        private object _lock = new object();

        [DllImport("User32.dll", EntryPoint = "SendMessage")]
        private static extern int SendMessage(IntPtr hWnd, int Msg, int wParam, int lParam);
        public void ShowInfo(string szText)
        {
            if(this.InvokeRequired)
            {
                Action<string> handler = new Action<string>(ShowInfo);
                this.Invoke(handler, new object[] { szText});
                return;
            }
            labelStatus.Text = szText;
            lock (_lock)
            {
                DateTime dt = DateTime.Now;
                if (this.richTextBox1.Text.Length > 10000)
                {
                    this.richTextBox1.Text = "";
                }
                this.richTextBox1.Text += dt.ToString("HH:mm:ss") + ": " + szText + "\r\n";
                if(!richTextBox1.IsDisposed)
                {
                    SendMessage(richTextBox1.Handle, 0x0115, 7, 0);
                }               
            }
        }

        private void buttonLed1Flash_Click(object sender, EventArgs e)
        {
            _ledControl.SetLed1(LedCommand.Flash);
        }

        private void buttonLed1On_Click(object sender, EventArgs e)
        {
            _ledControl.SetLed1(LedCommand.On);
        }

        private void buttonLed1Off_Click(object sender, EventArgs e)
        {
            _ledControl.SetLed1(LedCommand.Off);
        }

        private bool OnDisconnected()
        {
            if (_ledControl.Connected)
            {
                _ledControl.Close();
                buttonConnect.Enabled = true;
                buttonDisconnect.Enabled = false;
                labelStatus.Text = "设备已断开";
                Log.WriteAsync("设备已断开");
                return true;
            }
            return false;
        }

        private void buttonDisconnect_Click(object sender, EventArgs e)
        {
            OnDisconnected();
        }

        private int GetLedNum()
        {
            if (radioButton1.Checked)
            {
                return 1;
            }
            if (radioButton2.Checked)
            {
                return 2;
            }
            if (radioButton3.Checked)
            {
                return 3;
            }
            return 0;
        }

        private void SetLed(LedCommand cmd)
        {
            int num = GetLedNum();
            switch (num)
            {
                case 1:
                    _ledControl.SetLed1(cmd);
                    break;
                case 2:
                    _ledControl.SetLed2(cmd);
                    break;
                case 3:
                    _ledControl.SetLed3(cmd);
                    break;
                default:
                    break;
            }
        }

        private void buttonLedFlash_Click(object sender, EventArgs e)
        {
            SetLed(LedCommand.Flash);
        }

        private void buttonLedOn_Click(object sender, EventArgs e)
        {
            SetLed(LedCommand.On);
        }

        private void buttonLedOff_Click(object sender, EventArgs e)
        {
            SetLed(LedCommand.Off);
        }

        protected override void WndProc(ref System.Windows.Forms.Message m)
        {
            switch (m.Msg)
            {
                case WM_COPYDATA:
                    OnCustomMsgReceived(m);
                    break;
                case WindowsMessage.WM_CLOSE:
                    OnClosing();
                    break;
                default:
                    break;
            }
            base.WndProc(ref m);
        }

        /// <summary>
        /// 处理来自其他进程发来的消息
        /// </summary>
        /// <param name="m"></param>
        private void OnCustomMsgReceived(System.Windows.Forms.Message m)
        {
            COPYDATASTRUCT mystr = new COPYDATASTRUCT();
            Type mytype = mystr.GetType();
            mystr = (COPYDATASTRUCT)m.GetLParam(mytype);
            string jsonString = mystr.lpData;
            DeviceControlType controlType = (DeviceControlType)(int)m.WParam;
            if(controlType != DeviceControlType.LedControl)
            {
                string logInfo = $"收到的控制命令{controlType}无效.";
                ShowInfo(logInfo);
                Log.WriteAsync(logInfo);
                return;
            }
            try
            {
                LedActionArgs args = JsonConvert.DeserializeObject<LedActionArgs>(jsonString);
                LedControlCommand action = args.Command;
                switch (action)
                {
                    case LedControlCommand.Init:
                        ShowInfo("收到初始化设备的消息");
                        OnConnected();
                        break;
                    case LedControlCommand.Exit:
                        ShowInfo("收到关闭设备的消息");
                        if (OnDisconnected())
                        {
                            AsyncTask.StartDelayTask(1, this.Close, this);
                        }
                        else
                        {
                            Application.Exit();
                        }
                        break;
                    case LedControlCommand.SetLightOn:
                        ShowInfo("收到开灯的消息");
                        OnLightOn(args);
                        break;
                    case LedControlCommand.SetLightOff:
                        ShowInfo("收到关灯的消息");
                        OnLightOff(args);
                        break;
                    case LedControlCommand.SetLedFlash:
                        ShowInfo("收到闪灯的消息");
                        OnLedFlash(args);
                        break;
                    default:
                        break;
                }
            }
            catch (Exception ex)
            {
                Log.WriteExceptionAsync(ex.ToString());
            }          
        }

        private void OnLedFlash(LedActionArgs args)
        {
            try
            {                         
                if (args.LedNum == LEDS.LED1)
                {
                    _ledControl.SetLed1(LedCommand.Flash);
                }
                else if (args.LedNum == LEDS.LED2)
                {
                    _ledControl.SetLed2(LedCommand.Flash);
                }
                else if (args.LedNum == LEDS.LED3)
                {
                    _ledControl.SetLed3(LedCommand.Flash);
                }
            }
            catch (Exception)
            {

            }
        }

        private void OnClosing()
        {
            if (_ledControl.Connected)
            {
                _ledControl.Close();
            }
            Application.Exit();
        }

        private void OnLightOn(LedActionArgs args)
        {
            try
            {
                if (args.LedNum == LEDS.LED1)
                {
                    _ledControl.SetLed1(LedCommand.On);
                }
                else if (args.LedNum == LEDS.LED2)
                {
                    _ledControl.SetLed2(LedCommand.On);
                }
                else if (args.LedNum == LEDS.LED3)
                {
                    _ledControl.SetLed3(LedCommand.On);
                }
            }
            catch (Exception)
            {

            }
        }

        private void OnLightOff(LedActionArgs args)
        {
            try
            {
                if (args.LedNum == LEDS.LED1)
                {
                    _ledControl.SetLed1(LedCommand.Off);
                }
                else if (args.LedNum == LEDS.LED2)
                {
                    _ledControl.SetLed2(LedCommand.Off);
                }
                else if (args.LedNum == LEDS.LED3)
                {
                    _ledControl.SetLed3(LedCommand.Off);
                }
            }
            catch (Exception)
            {

            }
        }

        #region Notify MainForm about something

        /// <summary>
        /// 指示是否已经通知主窗体加载完成
        /// </summary>
        protected bool _bNotified = false;

        private string _appName = Path.GetFileNameWithoutExtension(Assembly.GetExecutingAssembly().CodeBase);
      
        /// <summary>
        /// 通知主窗体该进程启动已经完成
        /// </summary>
        protected void OnAppStartupFinished(int code = 1, string msg = "程序加载成功")
        {
            // 当父窗体为空时，不需要通知
            if (IntPtr.Zero == MonitoringWindowHandle || _bNotified)
            {
                Log.WriteAsync(string.Format("{0}获取父进程主窗口句柄为空，不启用进程监测.", _appName));
                return;
            }
            string sendMsg = string.Format("{0}#{1}#{2}", _appName, code, msg);
            var t = new Pipe(6, sendMsg, "MainStartup");
            Task.Factory.StartNew(new Action(t.run));
            Log.WriteAsync("已经通知主窗体启动完成: " + _appName);
            _bNotified = true;
        }
        #endregion

        private void FormLedControl_FormClosing(object sender, FormClosingEventArgs e)
        {

        }
    }
}
